package com.xpec.c4.db.hibernate.manager;

import java.lang.management.ManagementFactory;
import java.sql.Connection;

import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.jmx.StatisticsService;
/**
 *  Business数据库连接管理
 * @author wuweijun
 *  2012-06-14
 */
public class HibernateBusinessManager {
	/**
	 * log
	 */
	private static Log log = LogFactory.getLog(HibernateBusinessManager.class);

	/**
	 * Session Factory
	 */
	private static SessionFactory sessionFactory;

	/**
	 * Threadlocal Session
	 */
	private static final ThreadLocal<Session> session = new ThreadLocal<Session>();

	/**
	 * Transaction
	 */
	private static final ThreadLocal<Transaction> transaction = new ThreadLocal<Transaction>();

	/**
	 * @param connectBean
	 * @return
	 * @throws HibernateException
	 */
	public static Session getSession() throws HibernateException {
		Session s = session.get();

		if (s == null) {

			try {
				if (sessionFactory == null) {
					sessionFactory = ConfigurationManager
							.getHibernateConfiguration(ManagerType.BUSINESS)
							.buildSessionFactory();
					log.info("load default db cfg:"	+ ManagerType.BUSINESS);
					if(!ConfigurationManager.isAutoCreateTables()) {
						StatisticsService statsMBean = new StatisticsService();
						statsMBean.setSessionFactory(sessionFactory);
						statsMBean.setStatisticsEnabled(true);
	
						MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
						int hashCode = HibernateBusinessManager.class.getClassLoader().hashCode();
						mBeanServer.registerMBean(statsMBean, new ObjectName("Hibernate:application=hibernate2 " + hashCode));
					}
			}

				/*
				 * get the session
				 */
				s = sessionFactory.openSession();

			} catch (Exception e) {
				log.error("Error occurred when open a new session", e);
				throw new RuntimeException(e);
			}
		}

		session.set(s);
		s.clear();

		return s;
	}

	/**
	 * 关闭session
	 * 
	 * @throws HibernateException
	 */
	public static void closeSession() throws HibernateException {
		Session s = session.get();
		session.set(null);
		transaction.set(null);

		if (s != null) {
			try {
				s.close();
			} catch (HibernateException e) {
				log.error("Error closing the session", e);
				throw e;
			}
		}
	}

	/**
	 * 关闭session
	 * 
	 * @throws HibernateException
	 */
	public static void endSession() throws HibernateException {
		closeSession();
	}

	/**
	 * 事务开始
	 * 
	 * @throws HibernateException
	 */
	public static Session txBegin() throws HibernateException {
		Session s = null;
		try {
			s = getSession();
			Transaction t = s.beginTransaction();
			transaction.set(t);

		} catch (HibernateException e) {
			log.error("Error beginning a transaction: ", e);
			throw e;
		}

		return s;
	}

	/**
	 * 事务提交
	 * 
	 * @return
	 * @throws HibernateException
	 */
	public static boolean txCommit() throws HibernateException {
		Session s = session.get();
		Transaction t = transaction.get();

		if (s == null || t == null) {
			return false;
		} else {
			try {
				t.commit();
			} catch (HibernateException e) {
				log.error("Error committing transaction: ", e);
				throw e;
			}
		}

		return true;
	}

	/**
	 * 事务回滚
	 * 
	 * @return
	 * @throws HibernateException
	 */
	public static boolean txRollback() throws HibernateException {
		Session s = session.get();
		Transaction t = transaction.get();

		if (s == null || t == null) {
			return false;
		} else {
			try {
				t.rollback();
			} catch (HibernateException e) {
				log.error("Error rollbacking transaction: ", e);
				throw e;
			}
		}

		return true;
	}

	public static boolean txCommitFailRollbackClearSession() {
		try {
			txCommit();
			return true;
		} catch (HibernateException e) {
			txRollback();
			log.error("Transaction commit fail ! ", e);
			return false;
		} finally {
			// clearSession();
			endSession();
		}
	}

	/**
	 * get the current database connection.
	 * 
	 * @return
	 * @throws EPSTxException
	 */
	@SuppressWarnings("deprecation")
	public static Connection getConnection() throws HibernateException {
		try {
			return getSession().connection();
		} catch (HibernateException e) {
			log.error("Error getting the db connection: ", e);
			throw e;
		}
	}

	/**
	 * 清空Session
	 */
	public static void clearSession() {
		Session session = getSession();
		session.clear();
	}

	/**
	 * 更新Session
	 */
	public static void flushSession() {
		Session session = getSession();
		session.flush();
	}

	/**
	 * PO重新关联到session，状态由原来的脱管态变为游离态
	 */
	public static void rePersistent(Object obj) {
		if (obj == null)
			return;
		Session session = getSession();
		try {
			session.lock(obj, LockMode.NONE);
		} catch (HibernateException e) {
			try {
				if (session.contains(obj))
					session.evict(obj);
			} catch (Exception e1) {
			}
		}
	}

	public static void sessionEvict(Object obj) {
		Session session = getSession();
		session.evict(obj);
	}

	/**
	 * 获得数据库的名称
	 * 
	 * @return
	 */
	public static String getSchemaName() {
		return getSchemaName(ManagerType.BUSINESS);
	}

	/**
	 * 获得数据库的名称
	 * 
	 * @return
	 */
	public static String getSchemaName(ManagerType type) {

		String url = ConfigurationManager.getConnectionUrl(type);
		int firstIndex = url.lastIndexOf("/") + 1;
		int lastIndex = url.lastIndexOf("?");
		String schemaName = "";
		if (lastIndex > 0) {
			schemaName = url.substring(firstIndex, lastIndex);
		} else {
			schemaName = url.substring(firstIndex);
		}
		return schemaName;
	}
	
	public static void destroySessionFactory() {
		if(sessionFactory == null || sessionFactory.isClosed()) return;
		closeSession();
		sessionFactory.close();
		sessionFactory = null;
	}
}
